package cn.tpshion.devops.service.impl;

import cn.tpshion.devops.common.CoreException;
import cn.tpshion.devops.common.constant.RedisKey;
import cn.tpshion.devops.domain.dto.FlowTemplateDTO;
import cn.tpshion.devops.domain.dto.HistoryLogDTO;
import cn.tpshion.devops.domain.dto.TaskWorkDTO;
import cn.tpshion.devops.domain.entity.FlowHistory;
import cn.tpshion.devops.domain.entity.FlowTemplate;
import cn.tpshion.devops.domain.entity.TaskWork;
import cn.tpshion.devops.service.FlowService;
import cn.tpshion.devops.util.AssertUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FlowServiceImpl implements FlowService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Value("${node.workspace}")
    private String workspace;

    @Override
    public void saveTemplate(FlowTemplate flowTemplate) {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        hash.put(RedisKey.FLOW_TEMPLATE, flowTemplate.getName(), JSON.toJSONString(flowTemplate.getTaskWork()));
    }

    @Override
    public TaskWork getTemplate(FlowTemplateDTO dto) {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        AssertUtil.isFalse(hash.hasKey(RedisKey.FLOW_TEMPLATE, dto.getName()), "模版不存在");

        return JSON.parseObject(hash.get(RedisKey.FLOW_TEMPLATE, dto.getName()), TaskWork.class);
    }

    @Override
    public Set<String> templateList() {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        return hash.keys(RedisKey.FLOW_TEMPLATE);
    }

    @Override
    public void deleteTemplate(FlowTemplateDTO dto) {
        redisTemplate.opsForHash().delete(RedisKey.FLOW_TEMPLATE, dto.getName());
    }

    @Override
    public List<FlowHistory> historyList(TaskWorkDTO dto) {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        Map<String, String> entries = hash.entries(RedisKey.HISTORY + dto.getTaskId());
        if(ObjectUtils.isEmpty(entries)){
            return Collections.emptyList();
        }

        return entries.values().stream()
                .map(i -> JSON.parseObject(i, FlowHistory.class))
                .sorted(Comparator.comparing(FlowHistory::getBatchId).reversed())
                .collect(Collectors.toList());
    }

    @Override
    public List<String> historyLog(HistoryLogDTO dto) {
        try {
            StringBuilder builder = new StringBuilder();
            builder.append(workspace)
                    .append(File.separator)
                    .append(dto.getTaskId())
                    .append(File.separator)
                    .append("log")
                    .append(File.separator)
                    .append(dto.getBatchId() + ".log");

            File file = new File(builder.toString());
            log.info("historyLog file:{}", file.getPath());

            AssertUtil.isTrue(!file.exists() || file.isDirectory(), "读取日志失败");

            return FileUtils.readLines(file, StandardCharsets.UTF_8);
        }catch (Exception e){
            log.error("historyLog error:{}", e.getMessage(), e);
            throw new CoreException("读取日志失败");
        }
    }
}
